[HVM] Save/restore: save HPET registers
authorTim Deegan <Tim.Deegan@xensource.com>
Wed, 31 Jan 2007 18:15:00 +0000 (18:15 +0000)
committerTim Deegan <Tim.Deegan@xensource.com>
Wed, 31 Jan 2007 18:15:00 +0000 (18:15 +0000)
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
xen/arch/x86/hvm/hpet.c
xen/include/asm-x86/hvm/vpt.h
xen/include/public/hvm/save.h

index b0f64136699129716c6171847a076704cbf567df..dcc6ca3a4db07f49919a47f631cdcffb6bb5a103 100644 (file)
@@ -279,7 +279,7 @@ static void hpet_write(
              (h->hpet.timers[tn].config & HPET_TN_SETVAL) )
             h->hpet.timers[tn].cmp = new_val;
         else
-            h->period[tn] = new_val;
+            h->hpet.period[tn] = new_val;
         h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
         if ( hpet_enabled(h) && timer_enabled(h, tn) )
             hpet_set_timer(h, tn);
@@ -289,7 +289,7 @@ static void hpet_write(
     case HPET_T1_ROUTE:
     case HPET_T2_ROUTE:
         tn = (addr - HPET_T0_ROUTE) >> 5;
-        h->hpet.timers[tn].hpet_fsb[0] = new_val;
+        h->hpet.timers[tn].fsb = new_val;
         break;
 
     default:
@@ -351,21 +351,22 @@ static void hpet_timer_fn(void *opaque)
 
     hpet_route_interrupt(h, tn);
 
-    if ( timer_is_periodic(h, tn) && (h->period[tn] != 0) )
+    if ( timer_is_periodic(h, tn) && (h->hpet.period[tn] != 0) )
     {
         uint64_t mc = hpet_read_maincounter(h);
         if ( timer_is_32bit(h, tn) )
         {
             while ( hpet_time_after(mc, h->hpet.timers[tn].cmp) )
                 h->hpet.timers[tn].cmp = (uint32_t)(
-                    h->hpet.timers[tn].cmp + h->period[tn]);
+                    h->hpet.timers[tn].cmp + h->hpet.period[tn]);
         }
         else
         {
             while ( hpet_time_after64(mc, h->hpet.timers[tn].cmp) )
-                h->hpet.timers[tn].cmp += h->period[tn];
+                h->hpet.timers[tn].cmp += h->hpet.period[tn];
         }
-        set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->period[tn]));
+        set_timer(&h->timers[tn], 
+                  NOW() + hpet_tick_to_ns(h, h->hpet.period[tn]));
     }
 }
 
@@ -378,6 +379,35 @@ void hpet_migrate_timers(struct vcpu *v)
         migrate_timer(&h->timers[i], v->processor);
 }
 
+static int hpet_save(struct domain *d, hvm_domain_context_t *h)
+{
+    HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
+
+    /* Save the HPET registers */
+    return hvm_save_entry(HPET, 0, h, &hp->hpet);
+}
+
+static int hpet_load(struct domain *d, hvm_domain_context_t *h)
+{
+    HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
+    int i;
+
+    /* Reload the HPET registers */
+    if ( hvm_load_entry(HPET, h, &hp->hpet) )
+        return -EINVAL;
+    
+    /* Recalculate the offset between the main counter and guest time */
+    hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu);
+                
+    /* Restart the timers */
+    for ( i = 0; i < HPET_TIMER_NUM; i++ )
+        hpet_set_timer(hp, i);
+
+    return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load);
+
 void hpet_init(struct vcpu *v)
 {
     HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
index f51e16948a7aec1ff1eb1d37e8198a4e71163b2f..78684044266c12c9ea5b8dd2f846146f5e6a9ca8 100644 (file)
 #include <asm/hvm/vpic.h>
 #include <public/hvm/save.h>
 
-#define HPET_TIMER_NUM     3    /* 3 timers supported now */
-struct HPET {
-    uint64_t capability;        /* capabilities */
-    uint64_t res0;              /* reserved */
-    uint64_t config;            /* configuration */
-    uint64_t res1;              /* reserved */
-    uint64_t isr;               /* interrupt status reg */
-    uint64_t res2[25];          /* reserved */
-    uint64_t mc64;              /* main counter */
-    uint64_t res3;              /* reserved */
-    struct {                    /* timers */
-        uint64_t config;        /* configuration/cap */
-        uint64_t cmp;           /* comparator */
-        uint64_t hpet_fsb[2];   /* FSB route, not supported now */
-    } timers[HPET_TIMER_NUM];
-};
 
 struct HPETState;
 struct HPET_timer_fn_info {
@@ -55,11 +39,10 @@ struct HPET_timer_fn_info {
 };
 
 typedef struct HPETState {
-    struct HPET     hpet;
-    struct vcpu     *vcpu;
-    uint64_t        tsc_freq;
-    uint64_t        mc_offset;
-    uint64_t        period[HPET_TIMER_NUM];
+    struct hvm_hw_hpet hpet;
+    struct vcpu *vcpu;
+    uint64_t tsc_freq;
+    uint64_t mc_offset;
     struct timer timers[HPET_TIMER_NUM];
     struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM]; 
 } HPETState;
index fbf160b8ef04ab6c305ff7a6af89713d1afe2c15..48dfc187f0d6232c7baa324133c28bca9985fb83 100644 (file)
@@ -381,10 +381,40 @@ struct hvm_hw_rtc {
 DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc);
 
 
+/*
+ * HPET
+ */
+
+#define HPET_TIMER_NUM     3    /* 3 timers supported now */
+struct hvm_hw_hpet {
+    /* Memory-mapped, software visible registers */
+    uint64_t capability;        /* capabilities */
+    uint64_t res0;              /* reserved */
+    uint64_t config;            /* configuration */
+    uint64_t res1;              /* reserved */
+    uint64_t isr;               /* interrupt status reg */
+    uint64_t res2[25];          /* reserved */
+    uint64_t mc64;              /* main counter */
+    uint64_t res3;              /* reserved */
+    struct {                    /* timers */
+        uint64_t config;        /* configuration/cap */
+        uint64_t cmp;           /* comparator */
+        uint64_t fsb;           /* FSB route, not supported now */
+        uint64_t res4;          /* reserved */
+    } timers[HPET_TIMER_NUM];
+    uint64_t res5[4*(24-HPET_TIMER_NUM)];  /* reserved, up to 0x3ff */
+
+    /* Hidden register state */
+    uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
+};
+
+DECLARE_HVM_SAVE_TYPE(HPET, 10, struct hvm_hw_hpet);
+
+
 /* 
  * Largest type-code in use
  */
-#define HVM_SAVE_CODE_MAX 9
+#define HVM_SAVE_CODE_MAX 10
 
 
 /*